:- module(operator,['$foo$op'/3,'$foo$current_op'/3, op_table/1, op_token/3]).

:- dynamic(op_table/1).
op_table([]).

%% TOOD: I'd rather write retract(foo/1) than retractall(foo(_)).
'$foo$op'(Level, Fixity, Name) :-
 op_table(OldTable),
 ( select(_/Fixity/Name, OldTable, Table) -> true ; OldTable = Table ),
 retractall(op_table(_)),
 retractall(op_token(_,_,_)),
 sort(operator:op_level,[Level/Fixity/Name|Table],NewTable), %% TODO: Don't want to have to put operator: ther
 sort(operator:op_name_length,NewTable,TokenTable),
 assert(op_table(NewTable)),
 assert_tokenizers(TokenTable).

assert_tokenizers([]).
assert_tokenizers([_/_/Name|Xs]) :-
 make_tokenizer(Name, Tokenizer),
 assert(Tokenizer),
 assert_tokenizers(Xs).

'$foo$current_op'(Level, Fixity, Name) :- op_table(Table), member(Level/Fixity/Name, Table).

%% op_token/3 is operators as strings in decreasing order of token length
:- dynamic(op_token/3).
make_tokenizer(Name, op_token(Codes, CodesO, O)) :- atom_codes(Name, Codes), append(Codes, O, CodesO).

op_level(Level/_/_,Level).
op_name_length(_/_/Name,Length) :- atom_codes(Name, Codes), length(Codes, Length).

